package com.bitdf.txing.search.service.impl;

import com.alibaba.fastjson.JSON;
import com.bitdf.txing.common.utils.PageUtils;
import com.bitdf.txing.search.config.TxElasticConfig;
import com.bitdf.txing.search.constant.EsConstant;
import com.bitdf.txing.search.service.GroupSearchService;
import com.bitdf.txing.search.to.GroupInfoTo;
import com.bitdf.txing.search.to.GroupOutlineTo;
import com.bitdf.txing.search.to.SearchModelTo;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.core.CountRequest;
import org.elasticsearch.client.core.CountResponse;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.redisson.api.RBloomFilter;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;

/**
 * @author Lizhiwei
 * @date 2023/1/26 20:09:43
 * 注释：
 */
@Service
public class GroupSearchServiceImpl implements GroupSearchService {
    @Autowired
    RestHighLevelClient restHighLevelClient;

    @Autowired
    RBloomFilter bloomFilter;
    /**
     * 通过id获取组团信息
     * @param id
     * @return
     */
    @Override
    public GroupInfoTo getGroupById(Long id) throws IOException {

        if (!bloomFilter.contains(id)) {
            // 通过布隆过滤器检测到不存在 直接返回
            return null;
        }

        GetRequest getRequest = new GetRequest(EsConstant.GROUP_INDEX);
        GetRequest request = getRequest.id(id.toString());
        GetResponse response = restHighLevelClient.get(request, TxElasticConfig.COMMON_OPTIONS);
        String sourceAsString = response.getSourceAsString();
        GroupInfoTo groupInfoTo = JSON.parseObject(sourceAsString, GroupInfoTo.class);
        return groupInfoTo;
    }



    @Override
    public PageUtils searchGroup(SearchModelTo searchModelTo) throws IOException {

        //ToDo 校验工作还没做

        SearchRequest searchRequest = new SearchRequest();

        SearchSourceBuilder searchSource = SearchSourceBuilder.searchSource();



        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //查询内容
        boolQueryBuilder.must(QueryBuilders.multiMatchQuery(searchModelTo.getContent(), "title","content"));
        //status
        boolQueryBuilder.must(QueryBuilders.termQuery("status", searchModelTo.getStatus()));
        //活动地址
        boolQueryBuilder.must(QueryBuilders.matchQuery("address", searchModelTo.getAddress()));
        //组团分类
        boolQueryBuilder.must(QueryBuilders.boolQuery()
                .should(QueryBuilders.termQuery("parentCategoryId", searchModelTo.getCategoryId()))
                .should(QueryBuilders.termQuery("categoryId", searchModelTo.getCategoryId())));
        //查询某用户组团
        boolQueryBuilder.must(QueryBuilders.termQuery("userId", searchModelTo.getUserId()));
        //其他查询参数
        switch (searchModelTo.getSearchParam()){
            case "lastest":
                searchSource.sort("publishTime", SortOrder.DESC);
                break;
            case "comprehensive":
                //TODO 实现随机取出几个组团
                searchSource.sort("likeCount",SortOrder.DESC);
                break;
            case "hot" :
                searchSource.sort("viewCount", SortOrder.DESC);
                break;
        }
        //分页查询
        searchSource.from(searchModelTo.getLimit()*(searchModelTo.getPageNum()-1));
        searchSource.size(searchModelTo.getLimit());


        searchSource.query(boolQueryBuilder);

        System.out.println(searchSource.toString());

        searchRequest.source(searchSource);

        SearchResponse response = restHighLevelClient.search(searchRequest, TxElasticConfig.COMMON_OPTIONS);

        SearchHits hits = response.getHits();

        List<GroupInfoTo> list = new ArrayList<>();

        for (SearchHit hit : hits) {
            GroupInfoTo groupInfoTo = JSON.parseObject(hit.getSourceAsString(), GroupInfoTo.class);
            list.add(groupInfoTo);
        }
        //获取总记录数
        long value = hits.getTotalHits().value;
//        CountRequest countRequest = new CountRequest(EsConstant.GROUP_INDEX);


        PageUtils pageUtils = new PageUtils(list, Integer.parseInt(String.valueOf(value)), searchModelTo.getLimit(), searchModelTo.getPageNum());

        return pageUtils;
    }

    /**
     * 获取热点组团信息、排行榜
     * @param size 获取前多少个组团信息
     * @param target 0：获取三个分区热门组团 1：学习区 2：娱乐区 3：生活区 4：获取总的热门组团
     * @return
     */
    @Override
    public Map<Integer, List<GroupInfoTo>> getHotGroup(Integer size, Integer target) throws IOException {


        SearchRequest searchRequest = new SearchRequest(EsConstant.GROUP_INDEX);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        switch (target){
            case 0:
                break;
            case 1:
                sourceBuilder.query(QueryBuilders.termQuery("parentCategoryId", 1));
                break;
            case 2:
                sourceBuilder.query(QueryBuilders.termQuery("parentCategoryId", 2));
                break;
            case 3:
                sourceBuilder.query(QueryBuilders.termQuery("parentCategoryId", 3));
                break;
            case 4:
                break;
        }

        Map<Integer, List<GroupInfoTo>> map = new HashMap<>();
        List<GroupInfoTo>  list = new ArrayList<>();

        sourceBuilder.size(size);
        sourceBuilder.sort("viewCount", SortOrder.DESC);

        if (target==0){
            //学习区
            sourceBuilder.query(QueryBuilders.termQuery("parentCategoryId", 1));
            searchRequest.source(sourceBuilder);
            SearchResponse response = restHighLevelClient.search(searchRequest, TxElasticConfig.COMMON_OPTIONS);
            for (SearchHit hit : response.getHits()) {
                list.add(JSON.parseObject(hit.getSourceAsString(), GroupInfoTo.class));
            }
            map.put(1, list);
            //娱乐区
            searchRequest.source(new SearchSourceBuilder().query(QueryBuilders.termQuery("parentCategoryId", 2)));
            SearchResponse response1 = restHighLevelClient.search(searchRequest, TxElasticConfig.COMMON_OPTIONS);
            List<GroupInfoTo>  playList = new ArrayList<>();
            for (SearchHit hit : response1.getHits()) {
                playList.add(JSON.parseObject(hit.getSourceAsString(), GroupInfoTo.class));
            }
            map.put(2,playList);
            //生活区
            searchRequest.source(new SearchSourceBuilder().query(QueryBuilders.termQuery("parentCategoryId", 3)));
            SearchResponse response2 = restHighLevelClient.search(searchRequest, TxElasticConfig.COMMON_OPTIONS);
            List<GroupInfoTo>  liveList = new ArrayList<>();
            for (SearchHit hit : response2.getHits()) {
                liveList.add(JSON.parseObject(hit.getSourceAsString(), GroupInfoTo.class));
            }
            map.put(3,liveList);
        }else if(target==4){
            searchRequest.source(sourceBuilder);
            SearchResponse response = restHighLevelClient.search(searchRequest, TxElasticConfig.COMMON_OPTIONS);
            for (SearchHit hit : response.getHits()) {
                list.add(JSON.parseObject(hit.getSourceAsString(), GroupInfoTo.class));
            }
            map.put(4, list);
        }else {
            searchRequest.source(sourceBuilder);
            SearchResponse response = restHighLevelClient.search(searchRequest, TxElasticConfig.COMMON_OPTIONS);
            for (SearchHit hit : response.getHits()) {
                list.add(JSON.parseObject(hit.getSourceAsString(), GroupInfoTo.class));
            }
            map.put(target, list);
        }
        return map;
    }

    @Override
    public Boolean isGroupId(Long groupId) throws IOException {
        CountRequest countRequest = new CountRequest(EsConstant.GROUP_INDEX);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(
                QueryBuilders.matchQuery("id",groupId)
        );
        countRequest.source(sourceBuilder);
        CountResponse response = restHighLevelClient.count(countRequest, TxElasticConfig.COMMON_OPTIONS);
        long count = response.getCount();
        return count==1?true:false;
    }

    @Override
    public List<GroupOutlineTo> getGroupSimpleByGroupIds(Set<Long> groupIds) throws IOException {
        SearchRequest searchRequest = new SearchRequest(EsConstant.GROUP_INDEX);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.termsQuery("id", groupIds));
        searchRequest.source(sourceBuilder);
        SearchResponse response = restHighLevelClient.search(searchRequest, TxElasticConfig.COMMON_OPTIONS);
        List<GroupOutlineTo> list=new ArrayList<>();
        for (SearchHit hit : response.getHits()) {
            if (hit!=null){
                GroupInfoTo groupInfoTo = JSON.parseObject(hit.getSourceAsString(), GroupInfoTo.class);
                GroupOutlineTo outlineTo = new GroupOutlineTo();
                BeanUtils.copyProperties(groupInfoTo, outlineTo);
                if (outlineTo.getTitle().length()>15){
                    outlineTo.setTitle(outlineTo.getTitle().substring(0, 15)+"...");
                }
                list.add(outlineTo);
            }
        }
        return list;
    }

}
